
#include "stm32f10x.h"
#include "delay.h"
#include "sys.h"
#include "screen_ascii_char_type_8x16_1.h"


#define uint	unsigned int
#define uchar	unsigned char
#define ulong	unsigned long

#define SRC_LED1_OFF GPIO_SetBits  (GPIOC,GPIO_Pin_13);
#define SRC_LED1_ON  GPIO_ResetBits(GPIOC,GPIO_Pin_13);

#define LCD_CS  4
#define LCD_RST 3
#define LCD_RS  2
#define LCD_SDA 1
#define LCD_SCK 0

#define CS0()	GPIO_WriteBit(GPIOA, GPIO_Pin_4, Bit_RESET)
#define CS1()	GPIO_WriteBit(GPIOA, GPIO_Pin_4, Bit_SET)
#define RST0()	GPIO_WriteBit(GPIOA, GPIO_Pin_3, Bit_RESET)
#define RST1()	GPIO_WriteBit(GPIOA, GPIO_Pin_3, Bit_SET)
#define RS0()	GPIO_WriteBit(GPIOA, GPIO_Pin_2, Bit_RESET)
#define RS1()	GPIO_WriteBit(GPIOA, GPIO_Pin_2, Bit_SET)
#define SDA0()	GPIO_WriteBit(GPIOA, GPIO_Pin_1, Bit_RESET)
#define SDA1()	GPIO_WriteBit(GPIOA, GPIO_Pin_1, Bit_SET)
#define SCK0()	GPIO_WriteBit(GPIOA, GPIO_Pin_0, Bit_RESET)
#define SCK1()	GPIO_WriteBit(GPIOA, GPIO_Pin_0, Bit_SET)

/*写指令到LCD 模块*/
void jlxlcd_transfer_command(int data)
{
    char i;
    RS0();
    for(i = 0; i < 8; i++)
    {
        SCK0();
        if(data & 0x80)
            SDA1();
        else
            SDA0();
        SCK1();
        data = (data << 1);
    }
}

/*写数据到LCD 模块*/
void jlxlcd_transfer_data(int data)
{
    char i;
    RS1();
    for(i = 0; i < 8; i++)
    {
        SCK0();
        if(data & 0x80)
            SDA1();
        else
            SDA0();
        SCK1();
        data = (data << 1);
    }
}

/*LCD 模块初始化*/
void jlxlcd_init(void)
{
    Delay_Ms(10);

    //低电平复位
    CS0();
    RST0();
    Delay_Ms(10);
    //复位完毕
    RST1();
    Delay_Ms(10);

    CS0();

    jlxlcd_transfer_command(0xe2); /*软复位*/
    Delay_Ms(5);
    jlxlcd_transfer_command(0x2c); /*升压步聚1*/
    Delay_Ms(5);
    jlxlcd_transfer_command(0x2e); /*升压步聚2*/
    Delay_Ms(5);
    jlxlcd_transfer_command(0x2f); /*升压步聚3*/
    Delay_Ms(5);
    jlxlcd_transfer_command(0x23); /*0x23,选择内部电阻比例（Rb/Ra），可以调节显示对比度（粗调），可设置范围0x20～0x27*/
    jlxlcd_transfer_command(0x81); /*0x81,设置内部电阻微调，以设置液晶电压，此两个指令需紧接着使用*/
    jlxlcd_transfer_command(0x2f); /*0x1a,微调对比度的值，6 位电压值数据，00～3f 共64 级*/
    jlxlcd_transfer_command(0xa2); /*1/9 偏压比（bias）*/
    jlxlcd_transfer_command(0xa0); /*列扫描顺序：从左到右*/
    jlxlcd_transfer_command(0xc8); /*行扫描顺序：从上到下*/
    jlxlcd_transfer_command(0x40); /*0x40,起始行：第一行开始*/ //--> 原厂商提供的代码不正确
    jlxlcd_transfer_command(0xaf); /*开显示*/

    CS1();
    Delay_Ms(10);
}

/*全屏清屏*/
void jlxlcd_clear()
{
    unsigned char i, j;
    CS0();
    for(i = 0; i < 9; i++)
    {
        jlxlcd_transfer_command(0xb0 + i);
        jlxlcd_transfer_command(0x10);
        jlxlcd_transfer_command(0x00);
        for(j = 0; j < 132; j++)
        {
            jlxlcd_transfer_data(0x00);
        }
    }
    CS1();
}

/*显示16x16 点阵图像、汉字、生僻字或16x16 点阵的其他图标*/
void jlxlcd_display_graphic_16x16(uint page, uint column, uchar *dp)
{
    uint i, j;
    uchar page_address;
    uchar column_address_L, column_address_H;
    page_address = 0xb0 + page - 1;
    column_address_L = column & 0x0f;
    column_address_H = ((column >> 4) & 0x0f) + 0x10;
    CS0();
    //HighPD(ROM_CS);
    for(j = 0; j < 2; j++)
    {
        jlxlcd_transfer_command(page_address + j); /*设置页地址*/
        jlxlcd_transfer_command(column_address_H); /*设置列地址的高4 位*/
        jlxlcd_transfer_command(column_address_L); /*设置列地址的低4 位*/
        for (i = 0; i < 16; i++)
        {
            jlxlcd_transfer_data(*dp); /*写数据到LCD,每写完一个8 位的数据后列地址自动加1*/
            dp++;
        }
    }
    CS1();
}

/*显示8x16 点阵图像、ASCII, 或8x16 点阵的自造字符、其他图标*/
void jlxlcd_display_graphic_8x16(uint page, uchar column, uchar *dp)
{
    uint i, j;
    uchar page_address;
    uchar column_address_L, column_address_H;

    CS0();
    page_address = 0xb0 + page - 1;
    column_address_L = column & 0x0f;
    column_address_H = ((column >> 4) & 0x0f) + 0x10;
    for(j = 0; j < 2; j++)
    {
        jlxlcd_transfer_command(page_address + j); /*设置页地址*/
        jlxlcd_transfer_command(column_address_H); /*设置列地址的高4 位*/
        jlxlcd_transfer_command(column_address_L); /*设置列地址的低4 位*/
        for (i = 0; i < 8; i++)
        {
            jlxlcd_transfer_data(*dp); /*写数据到LCD,每写完一个8 位的数据后列地址自动加1*/
            dp++;
        }
    }
    CS1();
}

/*显示5*7 点阵图像、ASCII, 或5x7 点阵的自造字符、其他图标*/
void jlxlcd_display_graphic_5x7(uint page, uchar column, uchar *dp)
{
    uint col_cnt;
    uchar page_address;
    uchar column_address_L, column_address_H;
    page_address = page - 1; //0xb0+page-1;

    CS0();
    column_address_L = column & 0x0f;
    column_address_H = ((column >> 4) & 0x0f) + 0x10;
    jlxlcd_transfer_command(page_address); /*Set Page Address*/
    jlxlcd_transfer_command(column_address_H); /*Set MSB of column Address*/
    jlxlcd_transfer_command(column_address_L); /*Set LSB of column Address*/
    for (col_cnt = 0; col_cnt < 8; col_cnt++)
    {
        jlxlcd_transfer_data(*dp);
        dp++;
    }
    CS1();
}

/*显示8x16的字符串*/
void jlxlcd_display_ascii_8x16(uchar y, uchar x, uchar *text)
{
    uint begin = 0;
    uchar i, j = 0;
    uchar ascii[16];
    while(text[i] > 0x00)
    {
        begin = (text[i] - 0x20) * 16;
        for (j = 0; j < 16; j++)
        {
            ascii[j] = _ascii_array[begin + j]; //_ascii_array[begin+j];
        }
        jlxlcd_display_graphic_8x16(y * 2 - 1, (x - 1) * 8 + 1, ascii);
        x++;//x+=8;
        i++;
    }
}

/*显示8x16的数字变量*/
void jlxlcd_display_number_8x16(uchar y, uchar x, uchar number)
{
    uchar i = 0;
    uint begin = 0;
    uchar ascii[16];
    begin = (number + 0x30 - 0x20) * 16;
    for (i = 0; i < 16; i++)
    {
        ascii[i] = _ascii_array[begin + i]; //_ascii_array[begin+j];
    }
    jlxlcd_display_graphic_8x16(y * 2 - 1, (x - 1) * 8 + 1, ascii);
}

/*

uint fontaddr;

void display_GB2312_string(uchar y,uchar x,uchar *text)
{
	uchar i= 0;
	uchar addrHigh, addrMid, addrLow;
	uchar fontbuf32[32];
	uchar fontbuf16[16];
	while((text[i]>0x00))
	{
		if(((text[i]>=0xb0) &&(text[i]<0xf7)) && (text[i+1]>=0xa1))
		{
			//国标简体（GB2312）汉字在高通字库IC 中的地址由以下公式来计算：
			//Address = ((MSB - 0xB0) * 94 + (LSB - 0xA1)+ 846)*32+ BaseAdd; BaseAdd=0
			//由于担心8 位单片机有乘法溢出问题，所以分三部取地址
			fontaddr = (text[i]- 0xb0)*94;
			fontaddr += (text[i+1]-0xa1)+846;
			fontaddr = (ulong)(fontaddr*32);

			addrHigh = (fontaddr&0xff0000)>>16; //地址的高8 位,共24 位
			addrMid = (fontaddr&0xff00)>>8; //地址的中8 位,共24 位
			addrLow = fontaddr&0xff; //地址的低8 位,共24 位
			get_n_bytes_data_from_ROM(addrHigh,addrMid,addrLow,fontbuf32,32);
			//取32个字节的数据，存到"fontbuf32[32]"
			display_graphic_16x16(y,x,fontbuf32);//显示汉字到 LCD 上，y 为页地址，x 为列地址，fontbuf[]为数据
			i+=2;
			x+=16;
		}
		else if((text[i]>=0x20) &&(text[i]<=0x7e))
		{
			fontaddr = (text[i]- 0x20);
			fontaddr = (unsigned long)(fontaddr*16);
			fontaddr = (unsigned long)(fontaddr+0x3b7c0);

			addrHigh = (fontaddr&0xff0000)>>16;
			addrMid = (fontaddr&0xff00)>>8;
			addrLow = fontaddr&0xff;

			get_n_bytes_data_from_ROM(addrHigh,addrMid,addrLow,fontbuf16,16 );//取16 个字节的数据，存到"fontbuf[32]"
			display_graphic_8x16(y,x,fontbuf16);//显示8x16 的ASCII 字到LCD 上，y 为页地址，x 为列地址，fontbuf[]为数据
			i+=1;
			x+=8;
		}
		else
		{
			i++;
		}
	}
}

void display_string_5x7(uchar y,uchar x,uchar *text)
{
	unsigned char i= 0;
	unsigned char addrHigh,addrMid,addrLow ;
	while((text[i]>0x00))
	{
		if((text[i]>=0x20) &&(text[i]<=0x7e))
		{
			unsigned char fontbuf[8];
			fontaddr = (text[i]- 0x20);
			fontaddr = (unsigned long)(fontaddr*8);
			fontaddr = (unsigned long)(fontaddr+0x3bfc0);
			addrHigh = (fontaddr&0xff0000)>>16;
			addrMid = (fontaddr&0xff00)>>8;
			addrLow = fontaddr&0xff;
			//取8 个字节的数据，存到"fontbuf[32]"
			get_n_bytes_data_from_ROM(addrHigh,addrMid,addrLow,fontbuf,8);
			//显示5x7的ASCII字到LCD上，y为页地址，x为列地址，fontbuf[]为数据
			display_graphic_5x7(y,x,fontbuf);
			i+=1;
			x+=8;
		}
		else
		{
			i++;
		}
	}
}
*/

/*DEMO函数*/
void JLX12864G_086_Demo1(void)
{
    jlxlcd_display_ascii_8x16(1, 1, (uchar *)"12:59:11 - BCDAB");
    jlxlcd_display_ascii_8x16(2, 1, (uchar *)"DCA: -10.2345678");
    jlxlcd_display_ascii_8x16(3, 1, (uchar *)"{[(@#!=?$^&*%)]}");
    jlxlcd_display_ascii_8x16(4, 1, (uchar *)"1234567890123456");
}

void JLX12864G_086_Demo2(void)
{
    uint i;
    uchar view[5];

    jlxlcd_display_ascii_8x16(1, 1, (uchar *)"++++++++++++++++");
    jlxlcd_display_ascii_8x16(2, 1, (uchar *)"Current:");
    jlxlcd_display_ascii_8x16(3, 1, (uchar *)"Voltage:");
    jlxlcd_display_ascii_8x16(2, 15, (uchar *)"mV");
    jlxlcd_display_ascii_8x16(3, 15, (uchar *)"uA");
    jlxlcd_display_ascii_8x16(4, 1, (uchar *)"++++++++++++++++");

    while(1)
    {
        for (i = 55000; i < 59999; i++)
        {
            view[0] = i / 10000;
            view[1] = i % 10000 / 1000;
            view[2] = i % 1000 / 100;
            view[3] = i % 100 / 10;
            view[4] = i % 10;
            jlxlcd_display_number_8x16(2, 9, view[0]);
            jlxlcd_display_number_8x16(3, 9, view[0] * 7 % 10 - 2);
            jlxlcd_display_ascii_8x16 (2, 10, (uchar *)".");
            jlxlcd_display_ascii_8x16 (3, 10, (uchar *)".");
            jlxlcd_display_number_8x16(2, 11, view[1]);
            jlxlcd_display_number_8x16(3, 11, view[1] * 7 % 10 - 1);
            jlxlcd_display_number_8x16(2, 12, view[2]);
            jlxlcd_display_number_8x16(3, 12, view[2] * 7 % 10);
            jlxlcd_display_number_8x16(2, 13, view[3]);
            jlxlcd_display_number_8x16(3, 13, view[3] * 7 % 10);
            jlxlcd_display_number_8x16(2, 14, view[4]);
            jlxlcd_display_number_8x16(3, 14, view[4] * 7 % 10);
        }
    }
}

int main(void)
{
    u8 i;
    GPIO_InitTypeDef def;

    Delay_Init();
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);

    def.GPIO_Pin = GPIO_Pin_13;
    def.GPIO_Mode = GPIO_Mode_Out_PP;
    def.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOC, &def);

    def.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;
    def.GPIO_Mode = GPIO_Mode_Out_PP;	//推挽输出
    def.GPIO_Speed = GPIO_Speed_50MHz;	//IO口速度为50MHz
    GPIO_Init(GPIOA, &def);

    for(i = 0; i < 5; i++)
    {
        SRC_LED1_ON;
        Delay_Ms(60);
        SRC_LED1_OFF;
        Delay_Ms(60);
    }

    jlxlcd_init();
    Delay_Ms(10);
    jlxlcd_clear();
    Delay_Ms(5);

    JLX12864G_086_Demo1();

    Delay_Ms(25000);

    JLX12864G_086_Demo2();

    /* Infinite loop */
    while (1)
    {

    }
}


#ifdef  USE_FULL_ASSERT

/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{
    /* User can add his own implementation to report the file name and line number,
       ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */

    /* Infinite loop */
    while (1)
    {
    }
}
#endif
